from __future__ import annotations

import logging
import os
from pathlib import Path
from typing import Any, TYPE_CHECKING

from checkov.common.bridgecrew.vulnerability_scanning.integrations.twistcli import TwistcliIntegration
from checkov.common.util.str_utils import removeprefix

if TYPE_CHECKING:
    from checkov.common.bridgecrew.platform_integration import BcPlatformIntegration


class DockerImageScanningIntegration(TwistcliIntegration):
    async def report_results_async(
        self,
        twistcli_scan_result: dict[str, Any],
        bc_platform_integration: BcPlatformIntegration,
        bc_api_key: str,
        file_path: Path,
        **kwargs: Any,
    ) -> int:
        return await super().report_results_async(
            twistcli_scan_result=twistcli_scan_result,
            bc_platform_integration=bc_platform_integration,
            bc_api_key=bc_api_key,
            file_path=file_path,
            file_content=kwargs["file_content"],
            docker_image_name=kwargs["docker_image_name"],
        )

    def create_report(  # type:ignore[override]
        self,
        twistcli_scan_result: dict[str, Any],
        bc_platform_integration: BcPlatformIntegration,
        file_path: Path | str,
        file_content: str,
        docker_image_name: str,
        related_resource_id: str | None = None,
        root_folder: str | Path | None = None,
        error_lines: list[int] | None = None
    ) -> dict[str, Any]:
        if not bc_platform_integration.bc_source:
            logging.error("Source was not set")
            return {}

        results_dict = self._get_results_dict(twistcli_scan_result)
        path_prefix = str(root_folder) if root_folder else os.getenv("BC_ROOT_DIR", "")
        payload: dict[str, Any] = {
            "dockerImageName": docker_image_name,
            "dockerFilePath": removeprefix(str(file_path), path_prefix),
            "dockerFileContent": file_content,
            "type": "Image",
            "sourceId": bc_platform_integration.repo_id,
            "branch": bc_platform_integration.repo_branch,
            "sourceType": bc_platform_integration.bc_source.name,
            "vulnerabilities": self.get_vulnerabilities_for_report(results_dict),
            "packages": self.get_packages_for_report(results_dict),
            "relatedResourceId": related_resource_id,
            "errorLines": error_lines
        }
        if bc_platform_integration.cicd_details:
            payload["cicdDetails"] = bc_platform_integration.cicd_details
        return payload

    @staticmethod
    def _get_results_dict(twistcli_scan_result: dict[str, Any]) -> dict[str, Any]:
        try:
            results = twistcli_scan_result["results"]
            # we expect that there is exactly 1 scanned dokcer-image.
            if len(results) != 1:
                raise Exception(f'expected length of \"results\": 1. found: {len(results)}', results)
        except KeyError as exc:
            raise Exception("the key \"results\" expected to be existing in:", twistcli_scan_result) from exc
        result: dict[str, Any] = results[0]
        return result


docker_image_scanning_integration = DockerImageScanningIntegration()
